/** Une classe abstraite � utiliser pour le menu de lancement du jeu
 *  La classe de menu de votre jeu doit h�riter de cette classe :
 *    - d�finir la m�thode nomOptions qui renvoie un tableau de String qui corresponds aux 
 *    options possibles de votre menu
 *    - d�finir la m�thode lancerOption(int i) qui associe des actions aux options de votre menu 
 *    - d�finir les m�thodes wavAccueil et wavAide qui d�signent le fichier wave � lire pour l'accueil
 *    et l'aide.
 *    
 *  Ne pas modifier cette classe
 *  @author helene
 */

package devintAPI;

import noyau.Test;
import voix.Voix;
import wiiusej.wiiusejevents.physicalevents.ExpansionEvent;
import wiiusej.wiiusejevents.physicalevents.IREvent;
import wiiusej.wiiusejevents.physicalevents.MotionSensingEvent;
import wiiusej.wiiusejevents.physicalevents.WiimoteButtonsEvent;
import wiiusej.wiiusejevents.utils.WiimoteListener;
import wiiusej.wiiusejevents.wiiuseapievents.ClassicControllerInsertedEvent;
import wiiusej.wiiusejevents.wiiuseapievents.ClassicControllerRemovedEvent;
import wiiusej.wiiusejevents.wiiuseapievents.DisconnectionEvent;
import wiiusej.wiiusejevents.wiiuseapievents.GuitarHeroInsertedEvent;
import wiiusej.wiiusejevents.wiiuseapievents.GuitarHeroRemovedEvent;
import wiiusej.wiiusejevents.wiiuseapievents.NunchukInsertedEvent;
import wiiusej.wiiusejevents.wiiuseapievents.NunchukRemovedEvent;
import wiiusej.wiiusejevents.wiiuseapievents.StatusEvent;


import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import t2s.SIVOXDevint;

@SuppressWarnings("serial")
public abstract class MenuAbstrait extends JFrame implements KeyListener,
		ActionListener, WiimoteListener {

	// -------------------------------------------------------
	// les attributs
	// le nom du jeu
	protected final String nomJeu;

	// les noms des options
	private String[] nomOptions;

	// les boutons associ�s aux options
	private JButton[] boutonOption;

	// le nombre d'options
	private int nbOption;

	// Layout info
	private boolean LayoutQuestion;

	// attributs des textes et des boutons
	// � red�finir dans la classe concr�te si vous le souhaitez
	// en gardant de forts contrastes et peu de couleurs diff�rentes
	protected Font fonteBouton;
	protected Color couleurBouton;
	protected Color couleurBoutonSelectionne;
	protected Color couleurTexte;
	protected Color couleurTexteSelectionne;

	// les �l�ments qui parlent et que l'on veut pouvoir interrompre
	// protected SIVOXDevint voix;
	protected boolean voice;

	// l'option courante qui est s�lectionn�e
	private int optionCourante;

	// �l�ments de placement des composants
	private GridBagLayout placement; // le layout
	private GridBagConstraints regles; // les regles de placement
    protected int numquestion;
    protected int numTest;
    protected Test te;

    // -------------------------------------------------
	// les m�thodes abstraites � d�finir par h�ritage

	/**
	 * renvoie le tableau contenant le nom des options m�thode abstraite �
	 * d�finir par h�ritage
	 */
	protected abstract String[] nomOptions() throws Exception;

	// m�thodes � d�finir pour rendre la classe concr�te
	/**
	 * lance l'action associ�e au bouton n�i m�thode abstraite � d�finir par
	 * h�ritage PRECOND : i varie entre 0 et le nombre d'options possibles moins
	 * 1
	 */
	protected abstract void lancerOption(int i) throws Exception;

	/**
	 * renvoie le nom du fichier wav � lire pour l'accueil PRECOND : fichier est
	 * le chemin pour acc�der au fichier
	 */
	protected abstract String wavAccueil();

	/**
	 * renvoie le nom du fichier wav � lire pour l'aide PRECOND : fichier est le
	 * chemin pour acc�der au fichier
	 */
	protected abstract String wavAide();
	
	protected abstract String wavObjectif();
	
	protected abstract String wavTouche();

	// -------------------------------------------------------
	/**
	 * constructeur,
	 * 
	 * @param title
	 *            : le nom du jeu
	 * @param voice
	 *            : liste des options du menu
	 */    
    public MenuAbstrait(String title,boolean voice,Test te) throws Exception {
        super(title);
        nomJeu = title;
        optionCourante = -1;
        this.te=te;
        nomOptions = nomOptions(); // m�thode � rendre concr�te par h�ritage
        nbOption = nomOptions.length;
        this.LayoutQuestion = LayoutQuestion;
        creerAttributs();
        creerLayout();
        creerEntete();
        creerOption(nomOptions);
        setExtendedState(JFrame.MAXIMIZED_BOTH);
        setVisible(true);
        requestFocus();
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        addKeyListener(this);
        this.voice = voice;
        // if (voice) {
        // voix = new SIVOXDevint();
        // }
    }   

	public MenuAbstrait(String title, boolean voice, boolean LayoutQuestion) throws Exception {
		super(title);
		nomJeu = title;
		optionCourante = -1;
		nomOptions = nomOptions(); // m�thode � rendre concr�te par h�ritage
		nbOption = nomOptions.length;
		this.LayoutQuestion = LayoutQuestion;
		creerAttributs();
		creerLayout();
		creerEntete();
		creerOption(nomOptions);
		setExtendedState(JFrame.MAXIMIZED_BOTH);
		setVisible(true);
		requestFocus();
		setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		addKeyListener(this);
		this.voice = voice;
		// if (voice) {
		// voix = new SIVOXDevint();
		// }
	}
    public MenuAbstrait(String title, boolean voice, boolean LayoutQuestion,int numquestion,int numTest) throws Exception {
        super(title);
        nomJeu = title;
        this.numTest=numTest;
        this.numquestion=numquestion;
        optionCourante = -1;
        nomOptions = nomOptions(); // m�thode � rendre concr�te par h�ritage
        nbOption = nomOptions.length;
        this.LayoutQuestion = LayoutQuestion;
        creerAttributs();
        creerLayout();
        creerEntete();
        creerOption(nomOptions);
        setExtendedState(JFrame.MAXIMIZED_BOTH);
        setVisible(true);
        requestFocus();
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        addKeyListener(this);
        this.voice = voice;
        // if (voice) {
        // voix = new SIVOXDevint();
        // }
    }
    public MenuAbstrait(String title, boolean voice,int numTest, boolean LayoutQuestion) throws Exception {
        super(title);
        nomJeu = title;
        this.numTest=numTest;
        //this.numquestion=numquestion;
        optionCourante = -1;
        nomOptions = nomOptions(); // m�thode � rendre concr�te par h�ritage
        nbOption = nomOptions.length;
        this.LayoutQuestion = LayoutQuestion;
        creerAttributs();
        creerLayout();
        creerEntete();
        creerOption(nomOptions);
        setExtendedState(JFrame.MAXIMIZED_BOTH);
        setVisible(true);
        requestFocus();
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        addKeyListener(this);
        this.voice = voice;
        // if (voice) {
        // voix = new SIVOXDevint();
        // }
    }
	public MenuAbstrait(String title, boolean voice) throws Exception {
		this(title, voice, false);
	}

	// -------------------------------------------------------
	// m�thodes utilis�es par le constructeur

	/**
	 * cr�� les attributs (couleurs, fonte, ...)
	 */
	protected void creerAttributs() {
		if (!LayoutQuestion) {
			// la couleur des texte
			couleurTexte = Color.WHITE;
			couleurTexteSelectionne = new Color(10, 0, 150);
			// mise � jour des attributs des boutons
			fonteBouton = new Font("Tahoma", 1, 42);
			couleurBouton = couleurTexteSelectionne;
			couleurBoutonSelectionne = couleurTexte;
		} else {
			// la couleur des texte
			couleurTexte = Color.black;
			couleurTexteSelectionne = Color.yellow;
			// mise � jour des attributs des boutons
			fonteBouton = new Font("Serif", Font.BOLD, 50);
			couleurBouton = couleurTexteSelectionne;
			couleurBoutonSelectionne = couleurTexte;
		}
	}

	/**
	 * cr�� le layout pour placer les composants
	 */
	private void creerLayout() {
		placement = new GridBagLayout();
		regles = new GridBagConstraints();
		setLayout(placement);
		// par d�faut on �tire les composants horizontalement et verticalement
		regles.fill = GridBagConstraints.BOTH;
		// par d�faut, tous les composants ont un poids de 1
		// on les r�partit donc �quitablement sur la grille
		regles.weightx = 1;
		regles.weighty = 1;
		// espaces au bord des composants
		regles.insets = new Insets(10, 50, 10, 50);
		// pour placer en haut des zones
		regles.anchor = GridBagConstraints.NORTH;
	}

	/**
	 * cr�� l'ent�te avec le nom du jeu
	 */
	public void creerEntete() {

		// panel d'entete de la fen�tre
		JPanel entete = new JPanel();
		FlowLayout enteteLayout = new FlowLayout();
		enteteLayout.setAlignment(FlowLayout.CENTER);
		entete.setLayout(enteteLayout);
		entete.setBorder(new LineBorder(Color.GRAY, 8));
		if (LayoutQuestion)
			entete.setBackground(Color.black);

		// le label
		JLabel lb1 = new JLabel(nomJeu);
		lb1.setFont(new Font("Georgia", 1, 45));
		if (!LayoutQuestion) {
			lb1.setForeground(couleurTexteSelectionne);
			lb1.setBackground(couleurBoutonSelectionne);
		} else {
			lb1.setForeground(Color.white);
			lb1.setBackground(Color.white);
			Voix.read(nomJeu);

		}
		entete.add(lb1);

		// placement de l'entete en 1�re ligne, 1�re colonne
		regles.gridx = 1;
		regles.gridy = 1;
		placement.setConstraints(entete, regles);
		add(entete);
	}

	/**
	 * creer les boutons associ�s aux noms d'options
	 */
	private void creerOption(String[] noms) {
		// cr�ation des boutons
		// panel des boutons
		JPanel boutons = new JPanel();
		if (LayoutQuestion)
			boutons.setLayout(new GridLayout(2, 1));
		else
			boutons.setLayout(new GridLayout(nbOption, 1));
		// les boutons
		boutonOption = new JButton[nbOption];
		for (int i = 0; i < nbOption; i++) {
			creerBouton(i, noms[i]);
			boutons.add(boutonOption[i]);
		}
		// poids relatif de 3 (i.e 3 fois plus grand que l'ent�te)
		regles.weighty = 4;
		// placement des boutons en 2�me ligne, 1�re colonne
		regles.gridx = 1;
		regles.gridy = 2;
		placement.setConstraints(boutons, regles);
		add(boutons);
	}

	// pour cr�er un bouton associ� � un texte
	private void creerBouton(int i, String texte) {
		boutonOption[i] = new JButton();
		boutonOption[i].setText(texte);
		setPropertiesButton(boutonOption[i]);
	}

	// mettre � jour les propri�t�s des boutons
	protected void setPropertiesButton(JButton b) {
		b.setFocusable(false);
		b.setBackground(couleurBouton);
		b.setForeground(couleurTexte);
		b.setFont(fonteBouton);
		b.setBorder(new LineBorder(Color.BLACK, 5));
		b.addActionListener(this);
	}

	public void setTextOption(int i, String texte) {
		boutonOption[i].setText(texte);
	}

	// -------------------------------------------------------
	// m�thodes pour r�agir aux �v�nements clavier

	// �v�nements clavier
	public void keyReleased(KeyEvent e) {
	}

	public void keyTyped(KeyEvent e) {
	}

	public void keyPressed(KeyEvent e) {
		// if (voice) {
		// voix.stop();
		// }
		if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
			dispose();
		}
		// F1 = objectif
		if (e.getKeyCode() == KeyEvent.VK_F2) {
			Voix.readWav(wavAide());
		}
		if (e.getKeyCode() == KeyEvent.VK_F1) {
			Voix.readWav(wavObjectif());
		}
		if (e.getKeyCode() == KeyEvent.VK_H) {
			Voix.readWav(wavTouche());
		}
		if (e.getKeyCode() == KeyEvent.VK_SPACE){
			Voix.read(nomJeu);
		}
		
		// enter = s�lectionner l'option
		if (e.getKeyCode() == KeyEvent.VK_ENTER) {
           actionEnter();
		}
		// se d�placer dans les options vers le bas
		if (e.getKeyCode() == KeyEvent.VK_DOWN) {
			actionDown();
		}
		// se d�placer dans les options vers le haut
		if (e.getKeyCode() == KeyEvent.VK_UP) {
			actionUp();
		}
	}

	private void actionUp() {
		if (optionCourante == -1) {
			optionCourante = 0;
			setFocusedButton(optionCourante);
		} else {
			unFocusedButton(optionCourante);
			optionCourante = optionCourante - 1;
			if (optionCourante == -1)
				optionCourante = nbOption - 1;
			setFocusedButton(optionCourante);
		}
		
	}

	private void actionDown() {
		if (optionCourante == -1) {
			optionCourante = 0;
			setFocusedButton(optionCourante);
		} else {
			unFocusedButton(optionCourante);
			optionCourante = (optionCourante + 1) % nbOption;
			setFocusedButton(optionCourante);
		}
		
	}

	private void actionEnter() {
		 try {
             lancerOption(optionCourante); // m�thode � rendre concr�te par
         } catch (Exception e1) {
             e1.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
         }
         // h�ritage		
	}

	// activer l'option si clic sur le bouton
	public void actionPerformed(ActionEvent ae) {
		Object source = ae.getSource();
		for (int i = 0; i < nbOption; i++) {
			if (source == boutonOption[i]) {
				if (optionCourante != -1)
					unFocusedButton(optionCourante);
				optionCourante = i;
				setFocusedButton(optionCourante);
                try {
                    lancerOption(i);
                } catch (Exception e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }
            }
		}
	}

	
	public void changeColor(int i, Color color){
		System.out.println("Changement couleur pour bouton " + boutonOption[i].getText());
		boutonOption[i].setBackground(color);
		this.repaint();
	}
	// mettre le focus sur une option
	private void setFocusedButton(int i) {
		// if (voice) {
		// voix.playShortText(boutonOption[i].getText());
		// }
		boutonOption[i].setBackground(couleurBoutonSelectionne);
		boutonOption[i].setForeground(couleurTexteSelectionne);
		Voix.read(boutonOption[i].getText());
	}

	// enlever le focus d'une option
	private void unFocusedButton(int i) {
		boutonOption[i].setBackground(couleurBouton);
		boutonOption[i].setForeground(couleurTexte);
	}

	@Override
	public void onButtonsEvent(WiimoteButtonsEvent arg0) {
		if (arg0.isButtonUpJustReleased()) actionUp();
		if (arg0.isButtonDownJustReleased()) actionDown();
		if (arg0.isButtonAJustReleased()) actionEnter();
		
	}

	@Override
	public void onClassicControllerInsertedEvent(
			ClassicControllerInsertedEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onClassicControllerRemovedEvent(
			ClassicControllerRemovedEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onDisconnectionEvent(DisconnectionEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onExpansionEvent(ExpansionEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onGuitarHeroInsertedEvent(GuitarHeroInsertedEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onGuitarHeroRemovedEvent(GuitarHeroRemovedEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onIrEvent(IREvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onMotionSensingEvent(MotionSensingEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onNunchukInsertedEvent(NunchukInsertedEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onNunchukRemovedEvent(NunchukRemovedEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void onStatusEvent(StatusEvent arg0) {
		// TODO Auto-generated method stub
		
	}


}
